﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SwarmMappingAlpha
{
    /* The following XML class is a simple XML class meant to process the primitive XML
     * that comes from RoboRealm. This class can be removed and replaced with a more
     * extensive XML processing class as needed but is guaranteed to work with the RR
     * XML. Do NOT use this class for generic XML processing as it is included for
     * completeness and is intentionally kept simplistic to ease understanding 
     * */
    class XMLParsing
    {
        Dictionary<string, string> table = new Dictionary<string, string>();
        List<string> list = new List<string>();

        /*
        Unescapes strings that have been included in an XML message. This can be
        accomplished by a sequence of replace statements.
          &amp; -> &
          &quote; -> "
          &lt; -> <
          &gt; -> >
        */
        private String unescape(String txt)
        {
            txt = txt.Replace("&amp;", "&");
            txt = txt.Replace("&quote;", "\"");
            txt = txt.Replace("&lt;", "<");
            txt = txt.Replace("&gt;", ">");
            return txt;
        }

        public bool parse(String s)
        {
            table.Clear();
            return parse(s, table, null);
        }

        public List<string> parseVector(String s)
        {
            list.Clear();
            if (parse(s, null, list))
                return list;
            else
                return null;
        }

        public bool parse(String s, Dictionary<string, string> h, List<string> v)
        {
            bool isEndTag;
            byte[] txt = Encoding.ASCII.GetBytes(s);
            int i, j;
            int len = s.Length;
            StringBuilder[] keys = new StringBuilder[10];
            StringBuilder value = new StringBuilder();
            for (i = 0; i < 10; i++)
                keys[i] = new StringBuilder();
            int keyTop = -1;

            for (i = 0; i < len; )
            {
                // read in key
                if (txt[i] == '<')
                {
                    i++;
                    if (txt[i] == '/')
                    {
                        isEndTag = true;
                        i++;
                    }
                    else
                        isEndTag = false;

                    keyTop++;
                    keys[keyTop].Length = 0;
                    while ((i < len) && (txt[i] != '>'))
                    {
                        keys[keyTop].Append((char)txt[i]);
                        i++;
                    }
                    if (txt[i++] != '>')
                    {
                        Console.WriteLine("Missing close > tag");
                        return false;
                    }

                    if (isEndTag)
                    {
                        if (!keys[keyTop].ToString().Equals(keys[keyTop - 1].ToString()))
                        {
                            Console.WriteLine("Mismatched XML tags " + keys[keyTop] + " -> " + keys[keyTop - 1]);
                            return false;
                        }
                        keyTop -= 2;
                    }
                }
                else
                {
                    // read in value
                    value.Length = 0;

                    while ((i < len) && (txt[i] != '<'))
                    {
                        value.Append((char)txt[i]);
                        i++;
                    }

                    StringBuilder key = new StringBuilder();
                    for (j = 0; j <= keyTop; j++)
                    {
                        if (j > 0) key.Append('.');
                        key.Append(keys[j]);
                    }

                    String escapedValue = unescape(value.ToString());
                    if (h != null) h.Add(key.ToString(), escapedValue);
                    if (v != null) v.Add(escapedValue);
                }
            }

            return true;
        }

        public int getInt(String txt)
        {
            String s = (String)table[txt];
            if (s != null)
            {
                return Convert.ToInt32(s);
            }
            return 0;
        }

        public String getFirst()
        {
            if (table.Count == 0)
                return null;
            else
            {
                Dictionary<string, string>.Enumerator tableEnum = table.GetEnumerator();
                tableEnum.MoveNext();
                return tableEnum.Current.Value;
            }
        }
        /*
          // Test for XML class
          public static void main(String[] args)
          {
            XML xml = new XML();
            xml.parse("<response><width>100</width><height>200</height></response>");
            Console.WriteLine(xml.getInt("response.width"));
            Console.WriteLine(xml.getInt("response.height"));
          }
        */
    }
}
